package com.jdk.eight.stream;

import com.google.common.collect.Lists;

import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * ClassName: Stream
 * Description:
 * Date: 2016/7/7
 * Time: 16:04
 *
 * @author sm12652
 * @version V1.0.6
 */
public class StreamTest {

    public static void main(String[] args) {
//        wordCount();
//        wordCountStream();
//        operate();
//        reduce();
        collection();
    }

    public static void wordCount() {
        List<String> wordList = Lists.newArrayList("a1", "b22", "c333", "d4444", "e55555");
        int count = 0;
        for (String word : wordList) {
            if (word.length() > 5) {
                System.out.println(word);
                count++;
            }
        }
        System.out.println("count : " + count);
    }

    /**
     * Stream的版本
     */
    public static void wordCountStream() {
        List<String> wordList = Lists.newArrayList("a1", "b22", "c333", "d4444", "e55555");
        long count = wordList.stream().filter(word -> word.length() > 5).count();
        System.out.println("count: " + count);
        //并行
        long count2 = wordList.parallelStream().filter(word -> word.length() > 5).count();
        System.out.println("count2: " + count2);
    }

    /**
     * 创建Stream
     */
    public void create() {
        Stream<String> stream = Stream.of("I", "am", "wawlian");

        // Arrays类提供了一个stream(int[] array, int startInclusive, int endExclusive)和一系列重载方法来指定数组中哪些元素来创建Stream。
        Arrays.stream(new String[2]);

        // 空
        Stream<Object> empty = Stream.empty();

        // 可以使用Stream的generate()方法来创建无限的Stream。
        Stream.generate(new Supplier<String>() {
            @Override
            public String get() {
                return "Hello";
            }
        });
        Stream.generate(() -> "Hello");

        Stream.generate(() -> Math.random());
        Stream.generate(Math::random);// Class::staticMethod

        // Stream中还有一个iterate方法，Function
        Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);
    }

    /**
     * 一些操作
     */
    public static void operate() {

        // filter方法:这个接口实际上表现的是一种判定的规则
        Stream.of(1, 2, 3, 4).filter(t -> t.equals(1)).forEach(System.out::print);

        System.out.println();

        // map方法: map方法实际上是对集合中的所有元素执行某些变换操作，并生成新的Stream方法
        Lists.newArrayList("a", "b", "c").stream().map(String::toUpperCase).forEach(System.out::print);

        System.out.println();

//        取出每个字符串第一个字符的例子
        Lists.newArrayList("a1", "b2", "c3").stream().map(s -> s.charAt(0)).forEach(System.out::print);

        System.out.println();
        // 截取子Stream
        Stream.generate(Math::random).limit(5).forEach(System.out::print);

        System.out.println();
        Stream.iterate(1, x -> x + 1).limit(2).forEach(System.out::print);
        System.out.println();

        // 拼接Stream操作:concat
        Stream<Integer> integerStream = Stream.of(1);
        Stream<String> stream = Lists.newArrayList("a", "b", "c").stream();

        Stream.concat(integerStream, stream).forEach(System.out::print);

        System.out.println();
        // 有状态的中间操作,
        // 生成新的Stream都不以来源Stream的状态。但是有一些变换操作，实际上是需要根据源Stream的状态来进行的。比如，distinct方法。
        // 这个方法的实现明显就需要记录源Stream的状态。除此之外，还有一系列的Stream sorted()方法，可以将源Stream变成排好序的新Stream。举个例子：
        Lists.newArrayList("c333", "b22", "a1").stream().sorted(String::compareTo).forEach(System.out::println);
        Lists.newArrayList("c333", "b22", "a1").stream().sorted((one, other) -> one.length() - other.length()).forEach(System.out::println);
    }

    public static void reduce() {
        ArrayList<String> strings = Lists.newArrayList("c333", "b22", "a1");
        Optional<String> maybeMax = strings.stream().max(String::compareTo);
        maybeMax.ifPresent(System.out::println);

        Optional<String> min = strings.stream().min((one, theOther) -> Integer.compare(one.length(), theOther.length()));
        min.ifPresent(System.out::println);

        System.out.println(strings.stream().count());

        // findFirst、allMatch、noneMatch、anyMatch
        ArrayList<String> words = Lists.newArrayList("c333", "b22", "a1", "a2");
        words.stream().filter(s -> s.startsWith("a")).findFirst().ifPresent(System.out::println);//a1

        System.out.println(words.stream().allMatch(s -> s.startsWith("a")));//false
        System.out.println(words.stream().anyMatch(s -> s.startsWith("a")));//true
        System.out.println(words.stream().noneMatch(s -> s.startsWith("a")));//false

        // sum的操作
        System.out.println(Stream.of(1, 2, 3, 4).reduce(0, (a, b) -> a + b));//10
        System.out.println(Stream.of(1, 2, 3, 4).reduce(0, Integer::sum));//10
    }

    public static void collection() {
        ArrayList<String> words = Lists.newArrayList("c333", "b22", "a1", "a2");

        // iterator
        Iterator<String> iterator = words.stream().iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.print(next + ",");
        }

        System.out.println();

        // toArray
        for (Object o : words.stream().toArray()) {
            System.out.print(o + ", ");
        }
        System.out.println();

        // forEach
        words.stream().forEach(System.out::print);

        System.out.println();
        // 转成新的List
        System.out.println(words.stream().filter(word -> word.length() > 2).collect(Collectors.toList()));//[c333, b22]

        // 转成Set
        System.out.println(words.stream().collect(Collectors.toSet()));//[a1, a2, b22, c333]

        // 转成Map
        System.out.println(words.stream().collect(Collectors.toMap(String::toUpperCase, String::toLowerCase)));//{A1=a1, A2=a2, B22=b22, C333=c333}
    }
}
